#ifndef GAME_H
#define GAME_H

#include <iostream>
#include <vector>
#include <cmath>		//for absolute value function
#include "Display.h"
#include "boost\smart_ptr.hpp"
#include "Movables.h"
#include "Digdug.h"
#include "Monster.h"
#include "Projectile.h"
#include "Point.h"
#include "Utilities.h"	//for delta function
#include "LevelLoader.h"
#include "Bitmap.h"
#include "Map.h"

using std::vector;
using boost::scoped_ptr;
using boost::shared_ptr;

enum PlayResult {DIGDUG_DIES, MONSTER_DIES, NO_CHANGE};

/*! \brief Class which handles the majority of the game logic.
	
	This is a large class with many responsibilities. 
	Using composition, it incorporates all of the derived Movable classes. 
	
	There is one main public funcion which is called from main and is responsible for the movement of objects around the 
	game screen, score calculation and determining the state of the game after each move.
*/

class Game{

public:

	Game();

	/*! \brief A constructor which allows the user to start a game at a higher level than the default first level and to limit the 
		game to a specified number of levels before completion. 
	*/
	Game(int level, int numer_of_levels); //Overload Constructor for Game with a starting level

	/*! \brief The majority of the game's logic is implemented in this function through calls to private member functions.

		This function has several responsibilities, including:

		1) Sets the movement status of Dig Dug and his projectile in accordance with the keyboard input instruction which is passed into the funciton. 
		
		2) Auto routing of monsters which tracks Dig Dug's position and sets each of the monsters' movement route.
		
		3) Calls a function which sets the monsters to their disembodied 'ghost' form if they cannot track Dig Dug.
		
		4) Calls to each of the game objects' Move functions through private member functions.
		
		5) After each of the objects has been moved, the affect of this movement on the game including additions to player's score,
		   loss of Dig Dug's, the ending of a game or the movement onto a new level.

		If the game ends during a call to this function, this information is passed to the calling function in the return value.
		Otherwise, a value indicating that there has been no change in the game output is returned.
	*/
	GameResult update(Action instruction);

	//Get functions
	Map map();
	vector<Movables*> movable_ptrs();
	int score();
	int digdugLives();
	int level();
	vector <Monster> monsters();
	Digdug digdug();
	Projectile projectile();

private:

	//!Data Members
	Digdug _digdug;
	vector<Monster> _monsters;
	Projectile _projectile;
	Map _map;
	int _count;
	int _score;
	int _level;
	int _top_level;
	int _monster_kill_score;
	int _lives;

	//Private functions all called by the public Update function.

	//! \brief sets the movement status and direction of movement for Dig Dug or his Projectile depending upon the user's input
	//! which is passed into the function.
	void manageDigdugActions(Action instruction);
	
	/*! \brief This updates the monsters directions of movement and sets each monster to ghost form if they cannot reach Di Dug.
	
		To set a monster's direction , a call is made to a function contained in Monster class which ascertains the monster's next
		direction of movement based on auto routing or self routing.
	*/
	void updateMonsters();

	/*! \brief This loops through each of Game's existing movable objects and calls their Move functions.
	
		If a monster is killed it is deleted from the game. Dig Dug's projectile is then deleted from the map.
		Meaningful results of a move, such as Dig Dug's or a monster's death are returned to the calling function.
		If each object moves succesfully then a valuee indicating that there has been no change is returned to the calling function. 
	*/
	PlayResult moveObjects();
	/*! \brief A call is made to this function if Dig Dug's projectile collides with a monster. 
		The function destroys the monster hit by the projectile.

		The game map knows what type of object occupies each position on the map and therefore if a projectile collides with a monster this result can be known.
		However, the map does not know which monster occupies each position on the map.
		Using classic collision detection the exact monster hit by the projectile is identifed by comparing the projectile's location 
		to each of the monster's locations.
		When the correct monster is located it is deleted from the game and the projectile's status is reset to not shooting.
	*/
	bool destroyClosestMonster();
	
	//! \brief Calculates the score as a result of the object's movements after all movable objects have moved.
	GameResult manageScore(PlayResult move_result);

	//Functions called by the Game constructor.
	void loadMap(LevelLoader &level_data);
	void loadObjects(LevelLoader &level_data);
	void plotMovablesToMap();

};

#endif